﻿using System;
using System.ServiceModel;

namespace gixoom.Initiator.WcfWsHttp
{
    internal class InitiatorBlockStorage: IInitiatorBlockStorage, IDisposable
    {
        private gixoomWcfWsHttpTarget.TargetBlockStorageClient client;

        /// <summary>
        /// Creates InitiatorBlockStorage object.
        /// </summary>
        /// <param name="client">WCF client</param>
        /// <exception cref="System.ArgumentNullException"><i>client</i> is a null reference.</exception>
        public InitiatorBlockStorage(gixoomWcfWsHttpTarget.TargetBlockStorageClient client)
        {
            Ensure.ArgumentNotNull(client, "client");

            this.client = client;
        }

        ~InitiatorBlockStorage()
        {
            // TODO: the user can call this method as well. So it will be disposed more than 2 times.
            Dispose();
        }

        public void OpenConnection()
        {
            if (client.State != CommunicationState.Opened &&
                client.State != CommunicationState.Opening)
            {
                client.Open();
            }
        }

        public void CloseConnection()
        {
            if (client.State == CommunicationState.Opened)
            {
                client.Close();
            }
        }

        /// <summary>
        /// Stores the specified block in the storage.
        /// </summary>
        /// <param name="blockBytes">the block bytes</param>
        /// <returns>true if the block was successfully stored.</returns>
        /// <exception cref="System.ArgumentNullException"><i>blockBytes</i> is a null reference.</exception>
        public bool StoreBlock(byte[] blockBytes)
        {
            Ensure.ArgumentNotNull(blockBytes, "blockBytes");

            var result = client.StoreBlock(blockBytes);

            return result;
        }

        /// <summary>
        /// Retrieves block content by the specified array which represents the block id.
        /// </summary>
        /// <param name="blockId">the byte array which represents the block id</param>
        /// <returns>the content of the block by the specified block id or null if the block content
        /// cannot be retrieved</returns>
        /// <exception cref="System.ArgumentNullException"><i>blockIdBytes</i> is a null reference.</exception>
        public byte[] RetrieveBlockContent(byte[] blockIdBytes)
        {
            Ensure.ArgumentNotNull(blockIdBytes, "blockIdBytes");

            var result = client.RetrieveBlockContent(blockIdBytes);

            return result;
        }

        /// <summary>
        /// Checks whether the block with the specified block id exists.
        /// </summary>
        /// <param name="blockIdBytes">the block id to check existence of the block for</param>
        /// <returns>true if the block exists</returns>
        /// <exception cref="System.ArgumentNullException"><i>blockIdBytes</i> is a null reference.</exception>
        public bool ExistsBlock(byte[] blockIdBytes)
        {
            Ensure.ArgumentNotNull(blockIdBytes, "blockIdBytes");

            var result = client.ExistsBlock(blockIdBytes);

            return result;
        }

        public void Dispose()
        {
            CloseConnection();
        }
    }
}
